﻿#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkSphereSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkSmartPointer.h>
#include <vtkCamera.h>
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkNamedColors.h>
#include <vtkClipPolyData.h>
#include <vtkProperty.h>
#include <vtkPlane.h>
#include <vtkSTLReader.h>
#include <vtkPlaneCollection.h>
#include <vtkClipClosedSurface.h>
#include <vtkWorldPointPicker.h>
#include <vtkCutter.h>
#include <vtkInteractorStyleImage.h>

/// 用vtkCutter 切一个面出来

int main(int, char *[])
{
    std::string inputFilename = "D:/VTK/demo_pig20.stl";

    vtkSmartPointer<vtkSTLReader> reader = vtkSmartPointer<vtkSTLReader>::New();
    reader->SetFileName(inputFilename.c_str());
    reader->Update();

    double bounds[6];
    reader->GetOutput()->GetBounds(bounds);
    std::cout << "Bounds: ["
              << bounds[0] << ", " << bounds[1] << "] "
              << bounds[2] << ", " << bounds[3] << "] "
              << bounds[4] << ", " << bounds[5] << "] " << std::endl;


    vtkSmartPointer<vtkPlane> plane =
        vtkSmartPointer<vtkPlane>::New();
    plane->SetOrigin(10, 10, -10);
    plane->SetNormal(0, 0, -1);

    // Need a plane collection for clipping
//    vtkSmartPointer<vtkPlaneCollection>  planeCollection =
//            vtkSmartPointer<vtkPlaneCollection>::New();
//    planeCollection->AddItem(plane);

    // The clipper gennerates a clipped polygonial model
//    vtkSmartPointer<vtkClipClosedSurface> clipper =
//            vtkSmartPointer<vtkClipClosedSurface>::New();
//    clipper->SetInputConnection(reader->GetOutputPort());
//    clipper->SetClippingPlanes(planeCollection);
//    clipper->SetGenerateFaces(1);
//    clipper->SetScalarModeToLabels();
//    clipper->Update();

    vtkSmartPointer<vtkClipPolyData> clipPolyData =
        vtkSmartPointer<vtkClipPolyData>::New();
    clipPolyData->SetInputConnection(reader->GetOutputPort());
    clipPolyData->SetClipFunction(plane);
    clipPolyData->GenerateClippedOutputOn();
    clipPolyData->Update();

    vtkSmartPointer<vtkCutter> cut = vtkSmartPointer<vtkCutter>::New();
    cut->SetInputData(reader->GetOutput());
    cut->SetCutFunction(plane);
    cut->GenerateCutScalarsOn();
    cut->Update();

    vtkPolyData * cutPolyData = cut->GetOutput();
    cutPolyData->GetBounds(bounds);
    std::cout << "cut Bounds: ["
              << bounds[0] << ", " << bounds[1] << "] "
              << bounds[2] << ", " << bounds[3] << "] "
              << bounds[4] << ", " << bounds[5] << "] " << std::endl;


    vtkSmartPointer<vtkPolyDataMapper> mapper =
        vtkSmartPointer<vtkPolyDataMapper>::New();
//    mapper->SetInputConnection(reader->GetOutputPort());
    mapper->SetInputData(clipPolyData->GetClippedOutput());

    vtkSmartPointer<vtkActor> actor =
        vtkSmartPointer<vtkActor>::New();
    actor->SetMapper(mapper);

    vtkSmartPointer<vtkPolyDataMapper> outMapper =
        vtkSmartPointer<vtkPolyDataMapper>::New();
    outMapper->SetInputConnection(clipPolyData->GetOutputPort());

    vtkSmartPointer<vtkActor> outActor =
        vtkSmartPointer<vtkActor>::New();
    outActor->SetMapper(outMapper);

    // outMapper2
    vtkSmartPointer<vtkPolyDataMapper> outMapper2 =
        vtkSmartPointer<vtkPolyDataMapper>::New();
    outMapper2->SetInputConnection(cut->GetOutputPort());

    vtkSmartPointer<vtkActor> outActor2 =
        vtkSmartPointer<vtkActor>::New();
    outActor2->SetMapper(outMapper2);

    vtkSmartPointer<vtkNamedColors> colors =
        vtkSmartPointer<vtkNamedColors>::New();

    vtkSmartPointer<vtkRenderer> renderer =
        vtkSmartPointer<vtkRenderer>::New();
    renderer->SetBackground(colors->GetColor3d("Slate_grey").GetData());
    renderer->AddActor(actor);
    renderer->SetViewport(0, 0, 0.4, 1);

    vtkSmartPointer<vtkRenderer> outRenderer =
        vtkSmartPointer<vtkRenderer>::New();
    outRenderer->SetBackground(colors->GetColor3d("Slate_blue").GetData());
    outRenderer->AddActor(outActor);
    outRenderer->SetViewport(0.4, 0, 0.7, 1);

    vtkSmartPointer<vtkRenderer> outRenderer2 =
        vtkSmartPointer<vtkRenderer>::New();
    outRenderer2->SetBackground(colors->GetColor3d("Slate_blue").GetData());
    outRenderer2->AddActor(outActor2);
    outRenderer2->SetViewport(0.7, 0, 1, 1);

    vtkSmartPointer<vtkRenderWindow> renderWindow =
        vtkSmartPointer<vtkRenderWindow>::New();
    renderWindow->SetSize(900, 300);
    renderWindow->AddRenderer(renderer);
    renderWindow->AddRenderer(outRenderer);
    renderWindow->AddRenderer(outRenderer2);

    vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
        vtkSmartPointer<vtkRenderWindowInteractor>::New();
    renderWindowInteractor->SetRenderWindow(renderWindow);

//    vtkSmartPointer<vtkInteractorStyleTrackballCamera> style =
//        vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New();
    vtkSmartPointer<vtkInteractorStyleImage> style =
        vtkSmartPointer<vtkInteractorStyleImage>::New();
    renderWindowInteractor->SetInteractorStyle(style);

    renderWindow->Render();
    renderWindowInteractor->Initialize();
    renderWindowInteractor->Start();

    return EXIT_SUCCESS;
}
